import lodash from 'lodash';
import { isReactive } from 'vue';

// 获取指定sessionStorage数据
export const getSesstionStorage = function (key) {
  if (!key) return null;
  return sessionStorage.getItem(key) ? JSON.parse(sessionStorage.getItem(key)) : null;
};
// 保存指定sessionStorage数据
export const setSesstionStorage = function (key, data) {
  if (!data) return;
  sessionStorage.setItem(key, JSON.stringify(data));
};
//获取地址栏参数，用于问号型传参
export const urlParam = paramName => {
  const paramArray = window.location.href.match(/([^?=&]+)(=([^&]*))/g) || [];
  const reducer = (accumulator, currentValue) => {
    const arr = currentValue.split('=') || [];
    accumulator[arr[0]] = arr[1];

    return accumulator;
  };
  const result = paramArray.reduce(reducer, {});

  return paramName ? result[paramName] : result;
};
// 复制链接
export const copyUrl = function (url) {
  if (!url) return;
  const el = document.createElement('textarea');
  el.value = url;
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
};
// 随机生成姓名
export const getNameByRandom = function () {
  var familyNames = new Array(
    '赵',
    '钱',
    '孙',
    '李',
    '周',
    '吴',
    '郑',
    '王',
    '冯',
    '陈',
    '褚',
    '卫',
    '蒋',
    '沈',
    '韩',
    '杨',
    '朱',
    '秦',
    '尤',
    '许',
    '何',
    '吕',
    '施',
    '张',
    '孔',
    '曹',
    '严',
    '华',
    '金',
    '魏',
    '陶',
    '姜',
    '戚',
    '谢',
    '邹',
    '喻',
    '柏',
    '水',
    '窦',
    '章',
    '云',
    '苏',
    '潘',
    '葛',
    '奚',
    '范',
    '彭',
    '郎',
    '鲁',
    '韦',
    '昌',
    '马',
    '苗',
    '凤',
    '花',
    '方',
    '俞',
    '任',
    '袁',
    '柳',
    '酆',
    '鲍',
    '史',
    '唐',
    '费',
    '廉',
    '岑',
    '薛',
    '雷',
    '贺',
    '倪',
    '汤',
    '滕',
    '殷',
    '罗',
    '毕',
    '郝',
    '邬',
    '安',
    '常',
    '乐',
    '于',
    '时',
    '傅',
    '皮',
    '卞',
    '齐',
    '康',
    '伍',
    '余',
    '元',
    '卜',
    '顾',
    '孟',
    '平',
    '黄',
    '和',
    '穆',
    '萧',
    '尹',
  );
  var givenNames = new Array(
    '子璇',
    '淼',
    '国栋',
    '夫子',
    '瑞堂',
    '甜',
    '敏',
    '尚',
    '国贤',
    '贺祥',
    '晨涛',
    '昊轩',
    '易轩',
    '益辰',
    '益帆',
    '益冉',
    '瑾春',
    '瑾昆',
    '春齐',
    '杨',
    '文昊',
    '东东',
    '雄霖',
    '浩晨',
    '熙涵',
    '溶溶',
    '冰枫',
    '欣欣',
    '宜豪',
    '欣慧',
    '建政',
    '美欣',
    '淑慧',
    '文轩',
    '文杰',
    '欣源',
    '忠林',
    '榕润',
    '欣汝',
    '慧嘉',
    '新建',
    '建林',
    '亦菲',
    '林',
    '冰洁',
    '佳欣',
    '涵涵',
    '禹辰',
    '淳美',
    '泽惠',
    '伟洋',
    '涵越',
    '润丽',
    '翔',
    '淑华',
    '晶莹',
    '凌晶',
    '苒溪',
    '雨涵',
    '嘉怡',
    '佳毅',
    '子辰',
    '佳琪',
    '紫轩',
    '瑞辰',
    '昕蕊',
    '萌',
    '明远',
    '欣宜',
    '泽远',
    '欣怡',
    '佳怡',
    '佳惠',
    '晨茜',
    '晨璐',
    '运昊',
    '汝鑫',
    '淑君',
    '晶滢',
    '润莎',
    '榕汕',
    '佳钰',
    '佳玉',
    '晓庆',
    '一鸣',
    '语晨',
    '添池',
    '添昊',
    '雨泽',
    '雅晗',
    '雅涵',
    '清妍',
    '诗悦',
    '嘉乐',
    '晨涵',
    '天赫',
    '?傲',
    '佳昊',
    '天昊',
    '萌萌',
    '若萌',
  );

  var i = parseInt(10 * Math.random()) * 10 + parseInt(10 * Math.random());
  var familyName = familyNames[i];

  var j = parseInt(10 * Math.random()) * 10 + parseInt(10 * Math.random());
  var givenName = givenNames[i];

  return familyName + givenName;
};
// 从数组中获取指定obj
export const getArrayObjectByProp = (arr, prop, val) => {
  if (!Array.isArray(arr)) return null;
  let obj = null;
  arr.map(item => {
    if (item[prop] == val) obj = item;
  });
  return obj;
};
// 从数组中获取指定obj所处下标
export const getArrayIndexByProp = (arr, prop, val) => {
  if (!Array.isArray(arr)) return -1;
  let _index = -1;
  arr.map((item, index) => {
    if (item[prop] == val) {
      _index = index;
    }
  });
  return _index;
};

export function wait(time = rnd(500, 1000, Math.round)) {
  return new Promise(resolve => setTimeout(resolve, time));
}

export class LoStore {
  constructor(name, init = null, store = sessionStorage) {
    let $data;
    let nextTickErase = () => {
      Promise.resolve().then(() => {
        $data = undefined;
      });
    };
    let read = () => {
      if ($data !== undefined) return $data;
      $data = JSON.parse(store.getItem(name) || 'null') ?? init;
      nextTickErase();
      return $data;
    };
    let write = data => {
      if ($data === undefined) nextTickErase();
      $data = data;
      store.setItem(name, JSON.stringify(data));
    };

    write(read());

    const toRaw = object => {
      if (isReactive(object)) object = JSON.parse(JSON.stringify(object));
      return object;
    };

    this.get = key => lodash(read()).get(key);
    this.set = (key, value) => {
      value = toRaw(value);
      write(lodash(read()).set(key, value).value());
    };

    this.clearStore = () => {
      write(init);
    };

    this.indexOf = (key, find) => {
      find = toRaw(find);
      let collection = lodash(this.get(key) ?? []);
      return collection.findIndex(lodash.matches(find));
    };

    this.findOne = (key, find) => {
      find = toRaw(find);
      let collection = lodash(this.get(key) ?? []);
      return collection.find(lodash.matches(find));
    };

    this.remove = (key, find) => {
      let index = this.indexOf(key, find);
      if (index === -1) return;
      let collection = this.get(key);
      collection.splice(index, 1);
      this.set(key, collection);
    };

    this.removeAll = (key, matchValues) => {
      matchValues = toRaw(matchValues);
      let collection = lodash(this.get(key) ?? []);
      // record是collection的值，match是matchValues的值，用lodash.matches比对
      let pullCompare = (record, match) => lodash.matches(match)(record);
      collection = collection.pullAllWith(matchValues, pullCompare);
      this.set(key, collection.value());
    };

    this.save = (key, find, object) => {
      object = toRaw(object);
      let index = this.indexOf(key, find);
      let collection = this.get(key) ?? [];
      index === -1 ? collection.push(object) : (collection[index] = object);
      this.set(key, collection);
    };

    this.page = (key, page, size, filter) => {
      let records = this.get(key) ?? [];
      if (typeof filter === 'function') records = records.filter(filter);
      let total = records.length;
      let offset = (page - 1) * size;
      records = records.slice(offset, offset + size);
      return { records, total };
    };
  }
}

export function create(keys) {
  return (...values) => keys.reduce((ret, k, i) => ((ret[k] = values[i]), ret), {});
}

export function search(keyword, inKeys, compare) {
  if (!keyword) return () => true;
  let words = keyword.split(/\s+/g).filter(Boolean);
  if (compare == null || typeof compare !== 'function')
    compare = (rowValue, word) => rowValue.search(word) !== -1;

  return row => {
    return !inKeys.some(k =>
      words.some(word => {
        try {
          return !compare(row[k], word);
        } catch {
          return false;
        }
      }),
    );
  };
}

export function toOptions(object) {
  let options = [];
  for (let value in object) options.push({ value, label: object[value] });
  return options;
}

export function rnd(min = 0, max = 1, format = value => value) {
  let num = Math.random();
  num = num * (max - min);
  num = min + num;
  num = format(num);
  return num;
}

export function genId() {
  return Date.now().toString(36).slice(3) + Math.random().toString(36).slice(2, 7);
}

// 获取对象类型
export function typeOf(object) {
  return {}.toString.call(object).slice(8, -1);
}

// 是js基础对象
export function isObject(object) {
  return typeOf(object) === 'Object';
}

// 判断对象是否有某个key, 例：
// hasProp({name: null}, 'name') >> true
// hasProp({name: null}, 'value') >> false
// hasProp([], 'length') >> true
// hasProp([null], '0') >> true
export function hasProp(object, prop) {
  return {}.hasOwnProperty.call(object, prop);
}

// url参数字符串 >> 对象
export function qsParse(string) {
  return Object.fromEntries(new URLSearchParams(string).entries());
}

// 对象 >> url参数字符串
export function qsString(object) {
  return new URLSearchParams(object) + '';
}

// url拼接，支持对象拼接成参数
export function pathJoin(...pathSeq) {
  let url = '.';
  let query = {};
  // 没有用的路径片段
  let isNone = path => !path || ['./', '.'].includes(path);

  // 路径格式修正
  let urlize = string => {
    // 如果是相对路径 要补齐前面的 `./`
    if (!string.startsWith('/') && !string.startsWith('./') && !string.startsWith('../'))
      string = './' + string;
    // 去除重复的斜杠
    string = string.replace(/\/{2,}/g, '/');
    return string;
  };

  for (let fragment of pathSeq) {
    if (isObject(fragment)) {
      Object.assign(query, fragment);
      continue;
    }
    let [path, search] = fragment.split('?');
    if (search) Object.assign(query, qsParse(search));

    // 无效path不操作
    if (isNone(path)) continue;

    // 如果是有效path, url路径中最后一段不带斜杠需要被忽略
    if (!url.endsWith('/')) url = url.replace(/[^/]+$/, '');

    url = urlize(url);

    if (path.startsWith('/') || isNone(url)) {
      url = path;
      continue;
    }

    // 上级路径
    while (path.startsWith('../')) {
      path = path.replace(/^\.\.\//, '');
      if (/\/[^/]+\/$/.test(url)) {
        url = url.replace(/\/[^/]+\/$/, '/');
      }
    }

    if (path.startsWith('./')) path = path.replace(/^\.\//, '');
    url += path;
  }
  url = urlize(url);

  return url;
}

// CryptoJS重要数据加密
export function encrypt(str) {
  if (!str) return;
  return CryptoJS.AES.encrypt(str, 'estconsole').toString();
}
// CryptoJS重要数据解密
export function decrypt(encrypt) {
  if (!encrypt) return;
  return JSON.parse(CryptoJS.AES.decrypt(encrypt, 'estconsole').toString(CryptoJS.enc.Utf8));
}

export function clickUpload(accept = '*', multiple = false) {
  if (clickUpload.id && document.querySelector('#' + clickUpload.id)) {
    clickUpload.cancel?.();
  }

  const input = document.createElement('input');
  clickUpload.id = `click-upload_${Date.now().toString(36)}`;
  input.id = clickUpload.id;
  Object.assign(input, { type: 'file', accept, multiple });
  Object.assign(input.style, { position: 'fixed', zIndex: '-99', visibility: 'hidden' });

  document.body.appendChild(input);

  return new Promise((resolve, reject) => {
    let resolved = false;

    function onEnd() {
      resolved = true;
      input.removeEventListener('change', onChange);
      window.removeEventListener('focus', onFocus);
      input.remove();
      if (clickUpload.cancel === cancel) clickUpload.cancel = null;
    }

    function onChange() {
      if (resolved) return;
      resolve(input.files);
      onEnd();
    }

    // 通过window.onfocus判断 pc端用户选择文件"取消"
    function onFocus() {
      setTimeout(cancel, 1e3);
    }

    function cancel() {
      if (resolved) return;
      reject(new Error('user cancel'));
      onEnd();
    }

    clickUpload.cancel = cancel;

    input.addEventListener('change', onChange);
    window.addEventListener('focus', onFocus);

    input.click();
  });
}

export function fakeUpload(options) {
  const { file, onProgress } = options;
  let loaded = 0;
  let total = file.size;
  let chunk = 1024 * 1024;
  chunk = Math.min(Math.round(file.size / 24), chunk);
  chunk = Math.max(Math.round(file.size / (24 * 5)), chunk);
  let url = URL.createObjectURL(file);
  onProgress({ total, loaded, percent: 0 });
  let resolve,
    promise = new Promise(res => (resolve = res));
  let interval = setInterval(() => {
    loaded = Math.min(total, loaded + chunk);
    onProgress({ total, loaded, type: 'progress', percent: 100 * (loaded / total) });
    if (loaded >= total) {
      clearInterval(interval);
      resolve(url);
    }
  }, 1000 / 24);
  return promise;
}

export function fileUpload(files, name) {
  const blob = new Blob([files], { type: 'application/vnd.ms-excel' });
  const fileName = name;
  const link = document.createElement('a');
  if (
    !!window.ActiveXObject ||
    'ActiveXObject' in window ||
    navigator.userAgent.indexOf('Edge') > -1
  ) {
    navigator.msSaveBlob(blob, fileName);
  } else {
    link.style.display = 'none';
    link.href = URL.createObjectURL(blob);
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(link.href); // 释放URL 对象
    document.body.removeChild(link);
  }

  // let blob = new Blob([result], { type: 'application/xlsx' });
  // let url = window.URL.createObjectURL(blob);
  // let link = document.createElement('a');
  // link.href = url;
  // link.download = '卡券清单.xlsx';
  // link.click();
  // URL.revokeObjectURL(url);
}
